RequestSeal.Discovery (RequestSeal v0.2.0)

Copy Markdown View Source

Explicit bounded HTTPS discovery of HTTP Message Signatures Directories, JWKS and Client ID Metadata Documents. Construct a Discovery.Source from trusted caller configuration. A message/key ID never defines a URL to fetch.

fetch/2 performs one discovery operation with no cache. Options are :timeout (1–300,000 milliseconds, capped by the source timeout) and :clock (arity-zero Unix-seconds function, default system time). Unknown/duplicate options reject. The caller starts SSL; the library starts no application, listener, store, timer or background refresh. A monitored worker enforces a single absolute deadline across DNS, TLS, redirects and CIMD's optional JWKS subresource, and terminates socket owners on caller death or timeout.

Source policy controls exact private-address exceptions, redirects and resource limits. Every address in a DNS response is vetted; TLS connects by tuple and checks its connected peer. Responses require HTTP 200 and the selected media type; framing rejects ambiguous Content-Length/Transfer-Encoding. Trailer signatures cannot establish a proof. Gzip is expanded under a separate bound. Content-coding tokens are case-insensitive; x-gzip is accepted as gzip per RFC 9110 Section 8.4.1.3. Unknown or stacked codings reject.

Required public JWK members produce RFC 7638/8037 SHA-256 key IDs. A supplied kid must equal that value by default. Explicit Source.key_id: :directory requires unique printable directory-assigned IDs while retaining thumbprints for identity, revocation and cache removal; private material and malformed keys reject the entire set. HTTP alg tokens map to the JOSE restriction held by PublicKey. Keys whose use/operation restrictions forbid verification, and not-yet-valid, expired or revoked keys, are not resolvable. Duplicate IDs reject among eligible entries only. Directory sources require thumbprint mode. Directory signatures use the existing RequestSeal.verify/3 contract to bind @authority;req, digest, created/expires, key ID and tag. Directory proof means cryptographic possession, never principal attribution. Proof selection uses the directory label or a directory-tagged member whose key ID names a published directory key. Unrelated labels are ignored; missing or invalid selected members reject.

resolver/2 bridges a snapshot or {cache, source} to Policy.key_resolver. It accepts only algorithms: [...], ignores label/tag and returns only {:ok, %{algorithm: ..., key: ...}} or :error. A key ID never selects a URL. Discovery.Cache is an optional caller-started bounded cache with explicit refresh/removal/invalidation; it never serves stale keys.

The generic resolver bridge evaluates cache freshness and key expiry with the cache's configured clock; snapshot resolution uses system wall time. This preserves the generic caller's explicit clock policy. Named profiles enforce their own key/proof validity clock independently of request-freshness policy.

Web Bot Auth protocol-00 Appendix C.4 states: "A verifier should not fetch the directory for every request." Freshness follows Cache-Control: max-age before Expires, accounting for Date and Age under RFC 9111. Without either freshness field, the default is 300 seconds, caller-configurable via min_ttl. Invalid or past Expires is immediately stale. max_ttl, key/signature expiry, and no-cache/no-store still bound freshness. Appendix C.5 states: "Negative cache entries should expire after no more than five minutes." Accordingly, negative_ttl cannot exceed 300 seconds. It also states: "Network failures, TLS failures, and 5xx responses should be treated as transient unless local policy says otherwise." This adapter marks 5xx :unexpected_status retryable and 4xx non-retryable; retry scheduling and decisions remain caller-owned.

Sources: Web Bot Auth protocol-00, CIMD-02, RFC 7638, RFC 8037, RFC 9110 Section 8.4.1.3, RFC 9111 Section 4.2.1, RFC 9112.

Summary

Functions

Fetch a configured source once under a cancellable absolute deadline.

Build a Policy resolver using source-selected IDs and an algorithm allowlist.

Functions

fetch(source, opts \\ [])

Fetch a configured source once under a cancellable absolute deadline.

resolver(input, opts)

Build a Policy resolver using source-selected IDs and an algorithm allowlist.