Explicit generic RFC 9421 acceptance policy; no implicit profile or required choices.
RFC 9421 Section 2.2.3 lowercases the authority host and omits default ports
(HTTP 80 and HTTPS 443). Coverage of @authority alone can accept the same
signature across http://example.com, http://example.com:80,
https://example.com, and https://example.com:443 when all other covered
values match. Require @scheme (or @target-uri) whenever scheme matters.
Plug supports @scheme; its unavailable exact target evidence prevents
coverage of @target-uri.
new/1 requires all six keys:
:algorithms— nonempty unique list of exactRequestSeal.CryptoHTTP tokens or supported{:jws, name}selections. The resolver's algorithm is authoritative; senderalgnever selects it. JWS requires senderalgto be absent.:components— serialized Structured Fields Inner List, at most 256 required component identifiers, with exact parameter identity and no metadata parameters."()"explicitly permits no required coverage. Duplicate identifiers reject.:key_resolver— arity-one function receiving keyid (binary or nil), label (binary), and tag (binary or nil) in a map. Returns{:ok, %{algorithm: algorithm, key: public_key_or_verification_function}}or:error. HMAC secret custody stays inside an arity-three function(algorithm, base, signature), returning:okor{:error, term}. Optional:identitycarries a trustedRequestSeal.KeyIdentity. Public keys derive their canonical public identity and must agree with a supplied identity. Verification functions without one have unknown key equivalence. Identity values remain internal; no trusted principal association is inferred.:freshness—:not_evaluatedor a map containing all of:clock(arity zero, integer Unix seconds),:max_age(positive integer or nil),:skew(0..86,400),:require_expires(Boolean). Max-age requires created; expiration is exclusive, max-age inclusive. All checks must pass for some integer clock within[now - skew, now + skew]. Clock and max-age magnitudes are at most 999,999,999,999,999; RFC integer bounds apply to signature timestamps.:content—:not_requiredor a map with:kind(:contentor:representation), nonempty unique:algorithms("sha-256","sha-512"), and:section(:headersor:trailers). Require full coverage of precisely that digest field, recompute it, and require every supported present algorithm to be selected. Unknown algorithms cannot establish integrity.:replay—:not_requiredor a map with exactly:identifier(:nonce),:namespace(caller tenant/trust context, 1..256 bytes),:commitment(arity-one function returning{:ok, key}with 1..256 bytes or:error),:store(RequestSeal.Replay.Store), and:timeout(1..300,000 ms). Required replay requires bounded freshness:require_expires: trueor max-age. After validation the function receives exactlyidentifier,algorithm,keyid,tag,created,expires, andprofile: %{name: :rfc9421}or a package-namespaced extension stamp; never a signature label. Its result is claimed once under the caller namespace. RequestSeal supplies no application commitment recipe. Nonce is an authenticated RFC 9421 signature parameter, limited to 1,024 bytes; absent/empty nonce rejects. Retention ends at the first rejected second: minimum ofexpires + skewandcreated + max_age + skew + 1, over present bounds.
Optional keys: :field_schemas defaults to %{} (lowercase field names to
validated RequestSeal.StructuredFields.Schema values; at most 1,024),
:extra_components defaults to :allow (or :reject for exact coverage),
:max_signatures defaults to 16 (1..64, counts dictionary encounters, including
repeats, before duplicate-label rejection). Unknown keys or invalid direct structs also reject.
new/1 returns {:error, RequestSeal.Error} with :invalid_policy, layer
:input, retryable false. No callback is invoked during construction.
Summary
Functions
Construct a fully explicit policy or return a bounded invalid-policy error.
Types
@type signer() :: (RequestSeal.Crypto.algorithm(), binary() -> {:ok, binary()} | {:error, term()})
@type t() :: %RequestSeal.Policy{ algorithms: [RequestSeal.Crypto.algorithm()], components: binary(), content: :not_required | map(), extra_components: :allow | :reject, field_schemas: map(), freshness: :not_evaluated | map(), key_resolver: (map() -> {:ok, %{ optional(:identity) => RequestSeal.KeyIdentity.t(), algorithm: RequestSeal.Crypto.algorithm(), key: RequestSeal.PublicKey.t() | verify_fun() }} | :error), max_signatures: 1..64, replay: :not_required | map() }
@type verify_fun() :: (RequestSeal.Crypto.algorithm(), binary(), binary() -> :ok | {:error, term()})
Functions
@spec new(map()) :: {:ok, t()} | {:error, RequestSeal.Error.t()}
Construct a fully explicit policy or return a bounded invalid-policy error.