RequestSeal.Profile (RequestSeal v0.1.0)

Copy Markdown View Source

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.

Verify a selected member under an explicit policy and package-namespaced profile.

Types

stamp()

@type stamp() :: %{
  :name => {atom(), atom()},
  optional(atom()) => atom() | integer() | binary()
}

Functions

dictionaries(message, max)

Parse paired signature dictionaries in encounter order under a member limit.

preflight(input, components, extra, freshness_policy)

@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.

verify_label(message, policy, label, input, signature, profile)

Verify a selected member under an explicit policy and package-namespaced profile.