Shared HTTP signature pipeline for profiles owned by extension packages.
This extension surface is unstable; pin RequestSeal exactly.
An extension selects its source-specific rules, then uses dictionaries/2 to
parse paired signature fields, preflight/4 to check coverage and freshness
before discovery, and verify_label/6 to verify its selected dictionary
member under an explicit RequestSeal.Policy. The input and signature values
come from the same label returned by dictionaries/2. Verification re-parses
the message under the policy's max_signatures and checks that both supplied
values equal that label's entries before resolving a key.
verify_label/6 does not accept :representation or :digest_state options.
Content checks can use retained message body bytes only; representation
policies and stream digest states require generic RequestSeal.verify/3
with its validated options.
Profile maps contain at most eight atom keys and require
name: {package, kind}, where both values are atoms and package is not
:request_seal, :rfc9421, or :web_bot_auth. Use a compile-time constant
in the extension module, never a name derived from wire input. Bare atom names, including the core-owned names
:rfc9421 and :web_bot_auth, reject as :invalid_profile at the :input layer.
Other values must be atoms, integers from -999,999,999,999,999 through
999,999,999,999,999, or binaries of at most 256 bytes.
This pipeline enforces the supplied generic policy, not an extension's
source-specific predicates. Extensions own those checks and any trusted
principal attribution. A profile stamp is not proof of profile enforcement;
consumers must allowlist trusted profiles and their verification code.
Replay commitments receive the selected profile in authenticated facts;
commitments must bind facts.profile to separate profile security scopes.
RequestSeal.Ash.scope/2 accepts only its core profile allowlist.
Summary
Functions
Parse paired signature dictionaries in encounter order under a member limit.
Check required coverage and freshness before resolving a selected key.
Check the semantic rules for one parsed RFC 9421 Signature-Input Inner List.
Verify a selected member under an explicit policy and package-namespaced profile.
Types
Functions
@spec dictionaries(RequestSeal.Message.t(), pos_integer()) :: {:ok, {[{binary(), RequestSeal.StructuredFields.Value.t()}], %{required(binary()) => RequestSeal.StructuredFields.Value.t()}}} | {:error, RequestSeal.Error.t()}
Parse paired signature dictionaries in encounter order under a member limit.
@spec preflight( RequestSeal.StructuredFields.Value.t(), binary(), :allow | :reject, :not_evaluated | map() ) :: {:ok, :not_evaluated | map()} | {:error, RequestSeal.Error.t()}
Check required coverage and freshness before resolving a selected key.
Check the semantic rules for one parsed RFC 9421 Signature-Input Inner List.
Accepts a RequestSeal.StructuredFields.Value with type: :inner_list,
ordered component items, and signature parameters. It delegates to the shared
signature-field validator: at most 256 components, unique component identities,
recognized derived components or lowercase field names, permitted component
parameters, and integer created/expires or string nonce/alg/keyid/tag.
Unknown signature parameters remain permitted under RFC 9421 Section 2.3.
An empty component list is permitted; profiles select required coverage.
Parse or validate the Structured Fields representation first under an RFC 8941 schema. This predicate checks signature semantics, not the complete Structured Fields grammar, parameter uniqueness, freshness, key trust, or cryptography. It does not parse wire binaries. Non-inner lists and malformed structures that cannot be inspected return false.
iex> alias RequestSeal.StructuredFields.{Schema, Value}
iex> {:ok, schema} = Schema.new(%{revision: :rfc8941, type: :list, item_types: [:string], inner_lists: true})
iex> {:ok, %Value{value: [input]}} = RequestSeal.StructuredFields.parse(~s[("@method" "@path");created=1618884473], schema)
iex> RequestSeal.Profile.valid_signature_input?(input)
true
iex> RequestSeal.Profile.valid_signature_input?(~s[("@method")])
false
@spec verify_label( RequestSeal.Message.t(), RequestSeal.Policy.t(), binary(), RequestSeal.StructuredFields.Value.t(), RequestSeal.StructuredFields.Value.t(), stamp() ) :: {:ok, RequestSeal.Verification.t()} | {:error, RequestSeal.Error.t()}
Verify a selected member under an explicit policy and package-namespaced profile.